/**
 * Copyright 1996 self.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 *
 * @author Ashin Wimalajeewa
 *
 * Note, this is a very old runtime library that I have evolved since 1996. I rarely use it
 * now because the Apache Commons project has made it obsolete.
 */
package self.xml;

import java.io.*;
import javax.xml.parsers.*;

import org.w3c.dom.*;

final public class DomUtils {
  static private DocumentBuilderFactory dbFactory;

  static public DocumentBuilder getDocumentBuilder() {
    try {
      return dbFactory.newDocumentBuilder();
    } catch ( ParserConfigurationException err ) {
      throw new IllegalStateException( err.getMessage() );
    }
  }

  static public void readListOfValues( Node elem, String[] heirarchy, java.util.List store ) throws DOMException {
    Node leaf = null, branch = elem;
    for ( int cntr = 0; cntr < heirarchy.length-1; cntr++ ) {
      NodeList list = branch.getChildNodes();
      int max = list.getLength();
      for ( int branchCntr = 0; branchCntr < max; branchCntr++ ) {
        leaf = list.item( branchCntr );
        if ( leaf.getNodeName().equals(heirarchy[cntr]) ) {
          branch = leaf;
          break;
        }
      }
    }

    NodeList leaves = branch.getChildNodes();
    int max = leaves.getLength();
    for ( int cntr = 0; cntr < max; cntr++ ) {
      leaf = leaves.item( cntr );
      if ( leaf.getNodeName().equals(heirarchy[heirarchy.length-1]) ) {
        String val = leaf.getFirstChild().getNodeValue();
        store.add( val );
      }
    }
  }

  static public void writeListOfValues( Element elem, String[] heirarchy, java.util.List values ) throws DOMException {
    Document doc = elem.getOwnerDocument();
    int max = heirarchy.length;
    Element last = null, owner = elem;
    for ( int cntr = 0; cntr < max-1; cntr++ ) {
      last = doc.createElement( heirarchy[cntr] );
      owner.appendChild( last );
      owner = last;
    }
    int maxValues = values.size();
    for ( int cntr = 0; cntr < maxValues; cntr++ ) {
      Element leaf = doc.createElement( heirarchy[max-1] );
      Text val = doc.createTextNode( values.get(cntr).toString() );
      leaf.appendChild( val );
      last.appendChild( leaf );
    }
  }

  static public String getElementAttribute( Node elem, String name ) {
    String val = elem.getAttributes().getNamedItem( name ).getNodeValue();
//    String decVal = SpecialCharacterUtils.decode( val );
    String decVal = val;
    return decVal;
  }

  static public String getElementAttribute( Node elem, String name, String defaultVal ) {
    try {
// asw 07/01/04
//      String val =  elem.getAttributes().getNamedItem( name ).getNodeValue();
//      String decVal = SpecialCharacterUtils.decode( val );
//      return decVal;
      return getElementAttribute( elem, name );
    } catch ( Exception err ) {
      return defaultVal;
    }
  }

  static public void setElementAttribute( Element elem, String name, String val ) {
//    String encVal = SpecialCharacterUtils.encode( val );
    String encVal = val;
    elem.setAttribute( name, encVal );
  }

  static public void setElementText( Element elem, String text ) {
//    String encVal = SpecialCharacterUtils.encode( text );
    String encVal = text;
    Text added = elem.getOwnerDocument().createTextNode( encVal );
    elem.appendChild( added );
  }

  static public String getElementText( Node elem ) {
    NodeList list = elem.getChildNodes();
    int max = list.getLength();
    Node data = null;
    for ( int cntr = max-1; cntr >= 0; cntr-- ) {
      data = list.item( cntr );
      if ( data.getNodeType() == Node.TEXT_NODE ) {
        String val =  data.getNodeValue();
//        String decVal = SpecialCharacterUtils.decode( val );
        String decVal = val;
        return decVal;
      }
    }
    return null;
  }

  static public Node getChildElementNode( Node parent, String childNodeName ) {
    Node ret = null, child = null;
    NodeList list = parent.getChildNodes();
    int max = list.getLength();
    for ( int cntr = 0; cntr < max; cntr++ ) {
      child = list.item( cntr );
      if ( child.getNodeType() != Node.ELEMENT_NODE )
        continue;
      if ( child.getNodeName().equals(childNodeName) ) {
        ret = child;
        break;
      }
    }
    return ret;
  }

  static public void print( PrintWriter out, Node node ) {
    int type = node.getNodeType();
    switch (type) {
      // print the document element
      case Node.DOCUMENT_NODE:
          out.println("<?xml version=\"1.0\" ?>");
          print( out, ((Document)node).getDocumentElement());
          break;

        // print element with attributes
      case Node.ELEMENT_NODE:
          out.print("\n<");
          out.print(node.getNodeName());
          NamedNodeMap attrs = node.getAttributes();
          for (int i = 0; i < attrs.getLength(); i++) {
            Node attr = attrs.item(i);
            out.print(" " + attr.getNodeName() +
                             "=\"" + attr.getNodeValue() +
                             "\"");
          }
          out.print(">");

          NodeList children = node.getChildNodes();
          if (children != null) {
            int len = children.getLength();
            for (int i = 0; i < len; i++)
              print(out, children.item(i));
          }

          break;

        // handle entity reference nodes
      case Node.ENTITY_REFERENCE_NODE:
          out.print("&");
          out.print(node.getNodeName());
          out.print(";");
          break;

        // print cdata sections
      case Node.CDATA_SECTION_NODE:
          out.print("<![CDATA[");
          out.print(node.getNodeValue());
          out.print("]]>");
          break;

        // print text
      case Node.TEXT_NODE:
          out.print(node.getNodeValue());
          break;

        // print processing instruction
      case Node.PROCESSING_INSTRUCTION_NODE:
          out.print("<?");
          out.print(node.getNodeName());
          String data = node.getNodeValue();
          out.print(" ");
          out.print(data);
          out.print("?>");
          break;
    }

    if (type == Node.ELEMENT_NODE) {
      out.print("</");
      out.print(node.getNodeName());
      out.print('>');
    }
  }

  static public void printToStandardOutput( Node node ) {
    PrintWriter prn = new PrintWriter( System.out );
    print( prn, node );
    prn.flush();
  }

  static {
    dbFactory = DocumentBuilderFactory.newInstance();
    dbFactory.setNamespaceAware( true );
  }
}